package se.webbzon.boltzmann.battle.strategy.playerstrategy;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.image.ImageObserver;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import se.webbzon.boltzmann.input.Button;
import se.webbzon.oschi01.worldcamera.WorldCameraHud;
import se.webbzon.oschi01.worldcamera.WorldCameraPane;

public class PSIconPage extends AbstractPSPage {
	
	// The icon rotation speed of the heads-up display (# of steps)
	private static final int rotationSpeed = 10;
	
	// The layout of this player strategy icon page
	private final PSIconPageLayout layout;
	
	// A list containing all the icons in this player strategy icon page
	private final List<AbstractPSIcon> icons;
	
	// The rotation of the icons in the page
	private double rotation;
		
	// The index of the selected icon
	private volatile int iconIndex;
		
	// Whatever the rotation is performed clockwise
	private volatile boolean clockwise;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new player strategy icon page with a given layout
	 * and a list of player strategy icons. **/
	public PSIconPage(	PSIconPageLayout layout) {
		this(null,layout);
	}
	
	/** Creates a new player strategy icon page with a given parent, layout
	 * and a list of player strategy icons. **/
	public PSIconPage(	AbstractPSPage parent,
						PSIconPageLayout layout) {
		super(parent);
		this.layout = layout;
		iconIndex = 0;
		rotation = 0;
		clockwise = false;
		
		icons = new ArrayList<AbstractPSIcon>();
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Adds an icon to this player strategy icon page. **/
	public boolean addIcon(AbstractPSIcon icon) {
		return icons.add(icon);
	}
	
	/** Removes an icon from this player strategy icon page. **/
	public boolean removeIcon(AbstractPSIcon icon) {
		return icons.remove(icon);
	}
	
	/** Returns the index of the selected icon in this player strategy
	 * icon page. **/
	public int getSelectionIndex() {
		return iconIndex;
	}
	
	/** Returns the selected icon in this player strategy icon page. **/
	public AbstractPSIcon getSelectedIcon() {
		return icons.get(iconIndex);
	}
	
	/** Returns the layout of this player strategy icon page. **/
	public PSIconPageLayout getLayout() {
		return layout;
	}
	
	/** Returns a list of all the player strategy icons in this player
	 * strategy icon page. **/
	public List<AbstractPSIcon> getIcons() {
		return Collections.unmodifiableList(icons);
	}
	
	/** Returns the number of icons in this player strategy icon page. **/
	public int icons() {
		return icons.size();
	}
	
	/** Returns the (n+1):th player strategy icon from this player
	 * strategy icon page. **/
	public AbstractPSIcon getIcon(int n) {
		return icons.get(n);
	}
	
	/** Draws the player strategy icon page in the given world camera heads-up
	 * display where the icons are rotated by a given amount (in radians)
	 * and where the index of the selected icon is provided. **/
	public void drawPage(WorldCameraHud hud, double rotation, int iconIndex) {
		
	}
	
	@Override public void onSelect(PlayerStrategyHud psh) {
		getSelectedIcon().onSelect(psh, this);
	}

	@Override public void onReturn(PlayerStrategyHud psh) {
		if (getParent() != null)
			psh.setPage(getParent());
	}

	@Override public void onPress(PlayerStrategyHud psh, Button button) {
		if (button == Button.DOWN) {
			if (iconIndex == 0)
				iconIndex = icons()-1;
			else
				iconIndex--;
			clockwise = false;
		} else if (button == Button.UP) {
			if (iconIndex == icons()-1)
				iconIndex = 0;
			else
				iconIndex++;
			clockwise = true;
		}
	}
	
	@Override public void onStep(PlayerStrategyHud psh) {
		final int icons = icons();
		final double dv = 2 * Math.PI / icons;
		final double dvdt = dv / rotationSpeed;
		final double toAngle = - iconIndex * dv;
		final double toX = Math.cos(toAngle);
		final double toY = Math.sin(toAngle);
		final double x = Math.cos(rotation);
		final double y = Math.sin(rotation);
		if (Math.hypot(toX - x, toY - y) < dvdt) {
			rotation = toAngle;
		} else {
			if (clockwise)
				rotation -= dvdt;
			else
				rotation += dvdt;
		}
	}

	@Override public void onDraw(PlayerStrategyHud psh, WorldCameraPane hud) {
		// Retrieve layout coefficients
		final ImageObserver o = hud.getImageObserver();
		final double iconRadius = layout.getIconRadius();
		final int	backgroundXOffset = layout.getBackgroundXOffset(),
					backgroundYOffset = layout.getBackgroundXOffset();
		final int	iconXOffset = layout.getIconXOffset(),
					iconYOffset = layout.getIconYOffset();
		final int	textXSpacing = layout.getTextXSpacing(),
					textYOffset = layout.getTextYOffset();
		final int	backgroundWidth = layout.getIconBackgroundImage().getWidth(o);
		final Font 	textFont = layout.getTextFont();
		final Image	backgroundImage = layout.getIconBackgroundImage();
		final int icons = icons();
		final Dimension d = new Dimension();
		hud.getLayer().getDimension(d);
		int cx = d.width/2, cy = d.height/2;

		for (int i = 0; i < icons; i++) {
			// Calculate the center of the icon
			final double x = cx + iconRadius * Math.cos(i * 2 * Math.PI / icons + rotation);
			final double y = cy - iconRadius * Math.sin(i * 2 * Math.PI / icons + rotation);

			// Draw icon and icon text
			final AbstractPSIcon icon = getIcon(i);
			final int	bx = (int) (x + backgroundXOffset),
						by = (int) (y + backgroundYOffset);
			if (i != iconIndex)
				hud.setTransparency(0.5f);
			hud.drawImage(backgroundImage, bx, by);
			hud.drawImage(icon.getImage(), bx + iconXOffset, by + iconYOffset);
			hud.setTransparency(1);

			hud.setFont(textFont);
			hud.setColor(Color.black);
			final int 	textX = bx + backgroundWidth + textXSpacing,
						textY = by + textYOffset;
			hud.drawString(icon.getText(),textX,textY);
			hud.setColor(icon.getTextColor());
			hud.drawString(icon.getText(),textX - 1,textY - 1);
		}
	}

}
